package com.tony.demo.utils;

import android.os.Handler;
import android.os.Message;

/**
 * Copyright:
 * Created by TangJian on 2019/4/20.
 * Description:
 * Modified:
 */

@SuppressWarnings("all")
public abstract class CountDownTimer {

    /**
     * Millis since epoch when alarm should stop.
     */
    private long mMillisInFuture;

    /**
     * The interval in millis that the user receives callbacks
     */
    private final long mCountdownInterval;

    /**
     * boolean representing if the timer was cancelled
     */
    private boolean mCancelled = false;

    private static final int MSG = 1;

    /**
     * @param millisInFuture    The number of millis in the future from the call
     *                          to {@link #start()} until the countdown is done and {@link #onFinish()}
     *                          is called.
     * @param countDownInterval The interval along the way to receive
     *                          {@link #onTick(long)} callbacks.
     */
    public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture + countDownInterval;
        mCountdownInterval = countDownInterval;
    }

    /**
     * Cancel the countdown.
     */
    public synchronized final void cancel() {
        mCancelled = true;
        mHandler.removeMessages(MSG);
    }

    /**
     * Start the countdown.
     */
    public synchronized final CountDownTimer start(int delayMillis) {
        if (delayMillis % mCountdownInterval != 0) {
            throw new IllegalArgumentException("delayMillis must be integer multiple of mCountdownInterval");
        }

        if (mMillisInFuture % mCountdownInterval != 0) {
            throw new IllegalArgumentException("millisInFuture must be integer multiple of mCountdownInterval");
        }

        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG), delayMillis);
        return this;
    }

    /**
     * Start the countdown.
     */
    public synchronized final CountDownTimer start() {
        if (mMillisInFuture % mCountdownInterval != 0) {
            throw new IllegalArgumentException("millisInFuture must be integer multiple of mCountdownInterval");
        }

        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }

    /**
     * Callback fired on regular interval.
     *
     * @param millisUntilFinished The amount of time until finished.
     */
    public abstract void onTick(long millisUntilFinished);

    /**
     * Callback fired when the time is up.
     */
    public abstract void onFinish();

    /***
     * 判断是否正在倒计时状态
     */
    public boolean isRunning() {
        return !mCancelled;
    }

    // handles counting down
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }
                if (mMillisInFuture == 0) {
                    onFinish();
                } else {
                    onTick(mMillisInFuture - mCountdownInterval);
                    sendMessageDelayed(obtainMessage(MSG), mCountdownInterval);
                }
                mMillisInFuture -= mCountdownInterval;
                if (mMillisInFuture < 0) {
                    mMillisInFuture = 0;
                }
            }
        }
    };
}
